package com.shockweb.common.security;

import java.math.BigInteger;
import java.security.KeyPair;

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;

/**
 * sm2公私钥
 * @param privateKey
 */
public class SM2KeyPair{

    private static X9ECParameters x9ECParameters = GMNamedCurves.getByName("sm2p256v1");
    private static ECParameterSpec ecParameterSpec = new ECParameterSpec(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());


	private BCECPublicKey publicKey;
	private BCECPrivateKey privateKey;
	
	public SM2KeyPair(BCECPublicKey publicKey,BCECPrivateKey privateKey) {
		this.publicKey = publicKey;
		this.privateKey = privateKey;
	}
	
	public SM2KeyPair(byte[] publicKey,byte[] privateKey) {
    	SM2 sm2 = SM2.Instance();
        ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey); 
        this.publicKey = getPublickeyFromXY(userKey.normalize().getXCoord().toBigInteger(),
        		userKey.normalize().getYCoord().toBigInteger());
		this.privateKey = getPrivatekeyFromD(new BigInteger(privateKey));
	}
	
	public SM2KeyPair(String publicKeyBase64,String privateKeyBase64) {
		this(Utils.base64Decode(publicKeyBase64),Utils.base64Decode(privateKeyBase64));
	}
	
	public BCECPublicKey getPublicKey() {
		return publicKey;
	}

	public BCECPrivateKey getPrivateKey() {
		return privateKey;
	}
	
	public String getPublicKeyBase64() {
		return Utils.base64EncodeString(publicKey.getQ().getEncoded());
	}
	
	public byte[] getPublicKeyBytes() {
		return publicKey.getQ().getEncoded();
	}
	
	public String getPrivateKeyBase64() {
		return Utils.base64EncodeString(privateKey.getD().toByteArray());
	}
	
	public byte[] getPrivateKeyBytes() {
		return privateKey.getD().toByteArray();
	}
	
	public static BCECPrivateKey toPrivatekey(String privateKeyBase64) {
		return toPrivatekey(Utils.base64Decode(privateKeyBase64)); 
	}
	
	public static BCECPrivateKey toPrivatekey(byte[] privateKey) {
		return getPrivatekeyFromD(new BigInteger(privateKey));
	}
	
    private static BCECPrivateKey getPrivatekeyFromD(BigInteger d){
        ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecParameterSpec);
        return new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);
    }
    
	public static BCECPublicKey toPublickey(String publicKeyBase64) {
		return toPublickey(Utils.base64Decode(publicKeyBase64)); 
	}

	public static BCECPublicKey toPublickey(byte[] publicKey) {
    	SM2 sm2 = SM2.Instance();
        ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey); 
        return getPublickeyFromXY(userKey.normalize().getXCoord().toBigInteger(),
        		userKey.normalize().getYCoord().toBigInteger());
	}
	
    private static BCECPublicKey getPublickeyFromXY(BigInteger x, BigInteger y){
        ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(x9ECParameters.getCurve().createPoint(x, y), ecParameterSpec);
        return new BCECPublicKey("EC", ecPublicKeySpec, BouncyCastleProvider.CONFIGURATION);
    }
    
	@Override
	public String toString() {
		return "SM2KeyPair [publicKey=" + getPublicKeyBase64() + ", privateKey=" + getPrivateKeyBase64() + "]";
	}

}
